package com.homesoft.runtime.core.loaders;

import java.io.InputStream;
import java.util.HashSet;
import java.util.SortedMap;
import java.util.TreeMap;

import com.homesoft.runtime.log.ILog;
import com.homesoft.runtime.log.LogManager;

public class MetadataRuntimeInfo {
	
	private static final ILog logger = LogManager.getLogger(MetadataRuntimeInfo.class);
	private String metadataName;
	private MetadataRuntimeItemInfo first;
	
	public String getMetadataName() {
		return metadataName;
	}

	public MetadataRuntimeInfo(String metadataName) {
        this.metadataName = metadataName;
        first = new MetadataRuntimeItemInfo(this, LoadFolder.UserFolder);
    }
	
	/**
	 * 获取当前元数据在指定类型下的运行期类型
	 * @param key
	 * @return
	 */
    public Object getRuntimeType(MetadataRuntimeType key) {
        return first.getRuntimeType(key);
    }

    public MetadataLoader getMetadataLoader() {
        return first.GetMetadataLoader();
    }

    public InputStream getStream() {
        return first.getStream();
    }

    public InputStream getStream(LoadFolder folder) {
        return first.getStream(folder);
    }
    
    /**
     * 注册运行期类型
     */
    void addRuntimeType(MetadataRuntimeType key, LoadFolder folder, Object obj, Dependency dependency) {
        first.addRuntimeType(key, folder, obj, dependency);
    }

    /**
     * 设置指定位置下的资源加载器
     */
    void setMetadataLoader(LoadFolder folder, MetadataLoader loader, Dependency dependency) {
        first.setMetadataLoader(folder, loader, dependency);
    }
	
	private static class MetadataRuntimeItemInfo {
		private LoadFolder folder;
        private MetadataRuntimeInfo oThis;
        private SortedMap<MetadataRuntimeType, Object> types;
        private HashSet<Dependency> dependencys;
        private MetadataRuntimeItemInfo next;
        private MetadataLoader metadataLoader;
        
        public MetadataRuntimeItemInfo getNext() {
			return next;
		}

		public void setNext(MetadataRuntimeItemInfo next) {
			this.next = next;
		}

		MetadataRuntimeItemInfo(MetadataRuntimeInfo oThis, LoadFolder folder) {
            this.oThis = oThis;
            this.folder = folder;
            types = new TreeMap<MetadataRuntimeType, Object>();
            dependencys = new HashSet<Dependency>();
        }
        
        /**
         * 获取当前元数据在指定类型下的运行期类型
         * @param key
         * @return
         */
        public Object getRuntimeType(MetadataRuntimeType key) {
            Object result = types.get(key);
            
            if (result != null) {
            	return result;
            }
            
            if (this.next != null) {
            	return next.getRuntimeType(key);
            }
            
            return null;
        }
        
        public void addRuntimeType(MetadataRuntimeType key, LoadFolder folder, Object obj, Dependency dependency) {
        	if (folder == this.folder) {
                if (types.containsKey(key)) {
                	// TODO 需要实现平台异常处理机制
                    //throw new GTPMetadataException(MetadataErrorCode.METADATA_RUNTIME_TYPE_DUPLICATE,
                    //    new object[] { this._oThis._metadataName, folder, key, _types[key].AssemblyQualifiedName, type.AssemblyQualifiedName });
                }
                
                types.put(key, obj);
                AddDenpendency(dependency);
                return;
        	}
        	
        	if (next == null) {
                next = new MetadataRuntimeItemInfo(oThis, folder);
            }
        	
        	next.addRuntimeType(key, folder, obj, dependency);
        }
        
        public void setMetadataLoader(LoadFolder folder, MetadataLoader loader, Dependency dependency)
        {
        	if (folder == this.folder) {
        		if (metadataLoader == null) {
                    //logger.WriteTraceLog(LogLevel.Trace, m => m("注册元数据: {0}, 元数据来源: {1}, 所属目录:{2}", _oThis._metadataName, loader.ResourceType, folder));
                    metadataLoader = loader;
                } else if (loader != null) {
                    // 优先级_resourceLoader低于loader由loader替换
                    if (metadataLoader.getPriority() < loader.getPriority()) {
                        //logger.WriteTraceLog(LogLevel.Trace, m => m("覆盖元数据: {0}, 元数据来源: {1}, 所属目录:{2}", _oThis._metadataName, loader.ResourceType, folder));
                        metadataLoader = loader;
                    } else if (metadataLoader.getPriority() == loader.getPriority()) {
                    	// TODO 需要实现平台异常处理机制
                        //throw new GTPMetadataException(MetadataErrorCode.METADATA_LOADER_DUPLICATE,
                        //    new object[] { _metadataLoader.ResourceType, this._oThis._metadataName });
                    }
                }
                AddDenpendency(dependency);
        	}
        	
        	if (next == null) {
                next = new MetadataRuntimeItemInfo(oThis, folder);
            }
        	
        	next.setMetadataLoader(folder, loader, dependency);
        }
        
        private void AddDenpendency(Dependency dependency) {
            dependencys.add(dependency);
        }
        
        public java.io.InputStream getStream() {
            java.io.InputStream s = null;
            
            if (metadataLoader != null) {
                s = metadataLoader.getStream();
            }
            
            if (next != null) {
                s = next.getStream();
            }
            
            return s;
        }

        public java.io.InputStream getStream(LoadFolder folder) {
            java.io.InputStream s = null;
            
            if (this.folder == folder) {
                s = metadataLoader.getStream();
            }

            if (next != null) {
                s = next.getStream(folder);
            }

            return s;
        }

        public MetadataLoader GetMetadataLoader()
        {
            if (metadataLoader != null) {
            	return metadataLoader;
            }
            
            if (next != null) {
                return next.GetMetadataLoader();
            }
            
            return null;
        }
	}
}
